package com.wanji.gateway.handler;

import cn.hutool.core.util.StrUtil;
import com.wanji.gateway.constant.CommonConstant;
import com.wanji.gateway.device.DeviceManager;
import com.wanji.protocol.api.DeviceMessage;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.net.InetSocketAddress;

/**
 * 设备消息处理器：负责将Netty接收到的消息转换为Spring事件
 * 实现Netty与Spring Integration的事件桥接
 */
@Slf4j
@RequiredArgsConstructor
public class DeviceMessageHandler extends SimpleChannelInboundHandler<DeviceMessage> {

    private final DeviceManager deviceManager;

    /**
     * 处理接收到的设备消息
     * 将消息转换为DeviceMessageEvent事件并发布到Spring事件总线
     */
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, DeviceMessage message) {
        try {
            // 获取设备IP地址
            InetSocketAddress address = (InetSocketAddress) ctx.channel().remoteAddress();
            String deviceIp = address.getHostString();

            // 获取设备id
            String deviceId = message.getDeviceId();

            // 从注册表获取或注册设备ID
            deviceManager.registerDevice(deviceId, deviceIp, ctx.channel());
            deviceManager.publishEvent(message, deviceId);

            log.debug("接收到设备[{}]消息: {}", deviceId, message.getType());
        } catch (Exception e) {
            log.error("处理设备消息时发生异常", e);
        }
    }

    @Override
    public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
        String id = ctx.channel().attr(CommonConstant.DEVICE_ID).get();
        if (StrUtil.isNotBlank(id)) {
            DeviceManager.unregisterDevice(id);
        }
        super.channelUnregistered(ctx);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        // 打印异常并关闭连接
        log.error("处理设备消息时发生异常", cause);

        if (cause instanceof IOException) {
            log.warn("客户端断开了连接");
        } else {
            // 其他异常可记录日志或上报
            log.error("发生异常：{}", cause.getMessage());
        }
        ctx.close();
    }
}
